﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net.Http;
using System.ServiceModel.Channels;
using System.Text;
using System.Web;
using Newtonsoft.Json;

namespace Logistics.Utility
{
    /// <summary>
    /// 用于生成一些值的类
    /// </summary>
    public class Generator
    {


        /// <summary>
        /// 时间转时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        private int DateTimeToStamp(System.DateTime time)
        {
            System.DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
            return (int)(time - startTime).TotalSeconds;
        }

        #region 公共静态变量

        /// <summary>
        /// 订单号锁
        /// </summary>
        public static object SerialLocker = new object();

        #endregion

        #region 内部调用的私有方法

        /// <summary>
        /// 使用CSPRNG生成强随机数
        /// </summary>
        /// <param name="max">随机数的最大值</param>
        /// <returns>返回一个随机数</returns>
        private static int StrongRandom(int max)
        {
            var randomByte = new byte[4];
            var gen = new System.Security.Cryptography.RNGCryptoServiceProvider();
            gen.GetBytes(randomByte);
            var value = BitConverter.ToInt32(randomByte, 0);
            value = value % (max + 1);
            if (value < 0) value = -value;
            return value;
        }

        #endregion

        /// <summary>
        /// MD5加密方法
        /// </summary>
        /// <param name="value">需要加密的值</param>
        /// <param name="salt">加密盐值，默认不加盐</param>
        /// <returns>返回MD5加密值</returns>
        public static string Md5(string value, string salt = "")
        {
            var result = Encoding.Default.GetBytes(value + salt);
            var md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            var output = md5.ComputeHash(result);
            return BitConverter.ToString(output).Replace("-", "").ToUpper();
        }

        /// <summary>
        /// 生成一个随机字符串
        /// </summary>
        /// <param name="len">字符串长度</param>
        /// <returns>返回随机字符串</returns>
        public static string RandomChar(int len)
        {
            var builder = new StringBuilder();
            var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ~!@#$%^&*()".ToArray();
            for (var i = 0; i < len; i++)
            {
                builder.Append(chars[StrongRandom(chars.Length - 1)]);
            }
            return builder.ToString();
        }

        /// <summary>
        /// 获取客户端IP
        /// </summary>
        /// <param name="request">请求</param>
        /// <returns>返回客户端的IP</returns>
        public static string GetClientIP(HttpRequestMessage request)
        {
            if (request.Properties.ContainsKey("MS_HttpContext"))
            {
                return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
            }

            if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
            {
                var prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
                return prop.Address;
            }

            return null;
        }

        /// <summary>
        /// 获取枚举的键值对
        /// </summary>
        /// <param name="enum">枚举类型</param>
        /// <returns>返回枚举简直对</returns>
        public static List<object> GetNameValuePair(Type @enum)
        {
            var pairs = new List<object>();
            var values = Enum.GetValues(@enum);
            foreach (var value in values)
            {
                var name = Enum.GetName(@enum, value);
                pairs.Add(new
                {
                    Value = Convert.ToInt32(value),
                    Name = name,
                    Description = GetDescription(@enum, name)
                });
            }
            return pairs;
        }

        private static string GetDescription(Type @enum, string name)
        {
            var field = @enum.GetField(name);
            var attribute = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
            return attribute == null ? null : attribute.Description;
        }

        /// <summary>
        /// 将SQL语句重组为分页SQL
        /// </summary>
        /// <param name="sql">原sql语句</param>
        /// <param name="start">起始数据，从1开始</param>
        /// <param name="end">结束数据</param>
        /// <param name="sort">排序的字段</param>
        /// <param name="asc">是否正序（默认正序）</param>
        /// <returns>返回分页过的SQL语句</returns>
        public static string CreatePagingSql(string sql, int start, int end, string sort, bool asc = true)
        {
            var pagingSql =
                string.Format("SELECT * FROM ( SELECT ROW_NUMBER () OVER (ORDER BY {1} {2}) row_num, * FROM ({0}) origin_table ) row_table WHERE row_table.row_num BETWEEN {3} AND {4}"
                , sql
                , sort
                , asc ? "ASC" : "DESC"
                , start
                , end);
            return pagingSql;
        }

        /// <summary>
        /// 通过一堆id更新数据库时，使用该方法返回批量更新条件
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="ids">id集合</param>
        /// <param name="keyName">主键名称，默认ID</param>
        /// <returns>返回拼接的条件</returns>
        public static string CreateBatchUpdateCondition(string tableName, object[] ids, string keyName = "ID")
        {
            if (string.IsNullOrEmpty(tableName) || ids == null || ids.Length < 1)
            {
                return "";
            }
            var rows = ids.Select(id => string.Format("SELECT {0} AS COL", id)).ToList();
            return string.Format("FROM ({0}) AS BU_TABLE INNER JOIN {1} ON {1}.{2} = BU_TABLE.COL",
                string.Join(" UNION ", rows),
                tableName,
                keyName);
        }

        public static CustomHeader GetCustomHeader()
        {
            var arr = HttpContext.Current.Request.Headers.GetValues("Custom");
            var str = arr != null && arr.Length > 0 ? arr.First() : "";
            var obj = JsonConvert.DeserializeObject<CustomHeader>(str);
            return obj ?? new CustomHeader();
        }
    }
}
